package EjerciciosEnClase.EjercicioJuego;

import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

/**
* Juego en el cual múltiples Participantes toman parte.
*/
public class Juego {

	private List<Participante> participantes;

	/**
	* @post: Inicializa la instancia de Juego sin Participantes asociados.
	*/
	public Juego(){
		this.participantes = new LinkedList<Participante>();
	}
	
	/**
	* @post: Agrega nuevoParticipante a los Participantes del Juego.
	*/
	public void agregar(Participante nuevoParticipante){
		this.participantes.add(nuevoParticipante);
	}
	
	/**
	* @post: Devuelve todos los Participantes del Juego.
	*/
	public List<Participante> getParticipante(){
		return this.participantes;
	}
	
	/**
	* @post: Devuelve los Participantes del Juego ordenados alfabéticamente por nombre.
	*/
	public SortedSet<Participante> getParticipantesOrdenadosPorNombre(){
		Comparator<Participante> comparadorDeParticipantesPorNombre = new ComparadorDeParticipantesPorNombre();
		return this.ordenarParticipantes(comparadorDeParticipantesPorNombre);
	}
	
	/**
	* @post: Devuelve los Participantes del Juego ordenados por puntos descente y
	*		 tiempo ascendente.
	*/
	public SortedSet<Participante> getParticipantesOrdenadosPorResultado(){
		Comparator<Participante> comparadorDeParticipantesPorResultado = new ComparadorDeParticipantesPorResultado();
		return this.ordenarParticipantes(comparadorDeParticipantesPorResultado);
	}
	
	/**
	* @post: Devuelve los Participantes que tengan al menos tantos puntos como
	*		 puntosMínimos.
	*/
	public Set<Participante> getParticipantesConPuntos(int puntosMínimos){
		Set<Participante> conjuntoDeParticipantes = new HashSet<Participante>();
		Iterator<Participante> itParticipante = this.participantes.iterator();
		while(itParticipante.hasNext()){
			Participante proximoParticipante = itParticipante.next();
			if(proximoParticipante.getPuntos() >= puntosMínimos){
				conjuntoDeParticipantes.add(proximoParticipante);
			}
		}
		return conjuntoDeParticipantes;
	}
	
	/**
	* post: Devuelve los Participantes cuyo tiempo de juego esté
	*		comprendido entre tiempoMínimo y tiempoMáximo, ordenados por puntos.
	*/
	//TODO: achicar el metodo y reutilizar algo con this.getParticipantesConPuntos
	public SortedSet<Participante> getParticipantesConTiempo(int tiempoMinimo, int tiempoMaximo){
		Comparator<Participante> comparadorDeParticipantesPorResultado = new ComparadorDeParticipantesPorResultado();
		SortedSet<Participante> conjuntoDeParticipantes = new TreeSet<Participante>(comparadorDeParticipantesPorResultado); 
		List<Participante> listaDeParticipandes = new LinkedList<Participante>();
		Iterator<Participante> itParticipantes = this.participantes.iterator();
		while(itParticipantes.hasNext()){
			Participante proximoParticipante = itParticipantes.next();
			if(proximoParticipante.getTiempo() >= tiempoMinimo && tiempoMaximo >= proximoParticipante.getTiempo()){
				listaDeParticipandes.add(proximoParticipante);
			}
		}
		conjuntoDeParticipantes.addAll(listaDeParticipandes);
		return conjuntoDeParticipantes;
	}

	/**
	* @post: Devuelve un Mapa en el que se puede buscar un Participante por su nombre.
	*/
	public Map<String, Participante> getParticipantesPorNombre(){
		Map<String, Participante> mapaDeParticipantes = new HashMap<String, Participante>();
		Iterator<Participante> itParticipantes = this.participantes.iterator();
		while (itParticipantes.hasNext()) {
			Participante proximoParticipante = itParticipantes.next();
			mapaDeParticipantes.put(proximoParticipante.getNombre(), proximoParticipante);
		}
		return mapaDeParticipantes;
	}
	
	/**
	* @post: Devuelve un Mapa en el que se asocia para cada cantidad de puntos los
	*		 Participantes que lo obtuvieron.
	*/
	public Map<Integer, Set<Participante>> getParticipantesPorPuntos(){
//		TODO: Ejercicio 7
		Map<Integer, Set<Participante>> mapaDeParticipantes = new HashMap<Integer, Set<Participante>>();
		Set<Participante> grupoDeParticipantes = new HashSet<Participante>();
		Iterator<Participante> itParticipantes = this.participantes.iterator();
		while (itParticipantes.hasNext()) {
			Participante proximoParticipante = itParticipantes.next();
			int puntaje = proximoParticipante.getPuntos();
		}
		
		return mapaDeParticipantes;
	}
	
	/**
	* @post: Devuelve el promedio de puntos entre todos los Participantes del Juego.
	*/
	public double getPromedioDePuntos(){
		double promedio = 0;
		double puntajeTotal = 0; 
		if(this.participantes.size() > 0){
			Iterator<Participante> itParticipantes = this.participantes.iterator();
			while (itParticipantes.hasNext()) {
				puntajeTotal = puntajeTotal + itParticipantes.next().getPuntos();
			}
			promedio = puntajeTotal/this.participantes.size();
		}
		return promedio;
	}
	
	
	
	
	/**
	* @post: Ordena a los participantes bajo un criterio pedido.
	*/
	private SortedSet<Participante> ordenarParticipantes(Comparator<Participante> comparador){
		SortedSet<Participante> participantesOrdenados = new TreeSet<Participante>(comparador);
		participantesOrdenados.addAll(this.participantes);
		return participantesOrdenados;
	}
}